package com.dyh.quickdemozwei.clutch;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @Author: yhdong
 * @Date: 2022/1/19 15:39
 */
@Slf4j
public class TestCluch {

//    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(10);

    ByteBuffer byteBuffer = ByteBuffer.allocate(10);
    final Object visitBufferLock = new Object();
    final long apiOneSecondCallLimit = 3L;
    volatile AtomicLong apiCallCount = new AtomicLong(0L);

    volatile long autoSleepTime = 0L;

    @Test
    public void test(){

        /*用来清除限流计数*/
        Thread watch = new Thread(()->{

            for (;;){
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
//            apiCallCount.set(0);
                apiCallCount.getAndSet(0L);
            }

        });
        watch.start();

        Thread t = new Thread(()->{
            for (;;){
                consume();
            }
        });

        t.setName("consumeThread");
        t.start();

        /*模拟生产*/
        for (;;){
            try {
                produce();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void autoAdjustTime(){
        autoSleepTime+=50L;
//        if (autoSleepTime==0L)
//            autoSleepTime=50L;
//        else
//            autoSleepTime=2*50L;
    }

   public  void   produce() throws InterruptedException {
        synchronized (visitBufferLock){
            byteBuffer.put(0,(byte)0);
            byteBuffer.put(1,(byte)1);
            byteBuffer.put(2,(byte)2);
            byteBuffer.put(3,(byte)3);
            byteBuffer.put(4,(byte)4);
            byteBuffer.put(5,(byte)5);
            byteBuffer.put(6,(byte)6);
            byteBuffer.put(7,(byte)7);
            byteBuffer.put(8,(byte)8);
            byteBuffer.put(9,(byte)9);

            visitBufferLock.notify();
        }
    }


    void  consume()   {
        synchronized (visitBufferLock){
            try {
                visitBufferLock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            for (int i = 0;i<byteBuffer.limit();i++){

                 byte b = byteBuffer.get();
                log.info("自适应睡眠{}",autoSleepTime);
                if (autoSleepTime!=0L){

                    try {
                        Thread.sleep(autoSleepTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    outApi(b);
                }
                catch (ApiLimitException ae){
                    log.info("限流");
                    autoAdjustTime();
                }
                catch (Exception e) {
                    e.printStackTrace();

                }
            }
            byteBuffer.clear();


        }
    }



    class ApiLimitException extends RuntimeException{

    }

    public void outApi(byte b){
        apiCallCount.incrementAndGet();
        if (apiCallCount.intValue()>apiOneSecondCallLimit){
            throw new ApiLimitException();
        }
        try {
            Thread.sleep(100L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("消费 {}",b);


    }

//    void  consume(int [] data){
//        log.info("consume data=",data);
//    }
//
//    int [] produce(){
//        return new  int [] {1,3,4,5};
//    }
}
